/*
 * user_flash_spi_driver.c
 *
 *  Created on: Dec 20, 2023
 *      Author: dk007
 */


/*
 * user_spi_driver.c
 *
 *  Created on: Jan 30, 2023
 *      Author: dk007
 */
#include "user_includes.h"
#include "CH58x_common.h"
#include "sys_init.h"
#include "user_flash_spi_driver.h"
#include "user_external_voice_manager.h"

/*
 *
 * - Uniform 256-byte Page Program
- Uniform 256-byte Page Erase
- Uniform 4K-byte Sector Erase
- Uniform 32K/64K-byte Block Erase
- Full Chip Erase
 Hardware Controlled
 */

#if(USER_NOR_FLASH_EN)
#define FLASH_SPI_CS_LOW    USER_NRF_SPI_NSS_L()
#define FLASH_SPI_CS_HIGH   USER_NRF_SPI_NSS_H()

volatile static bool is_nor_flash_init_flag = false;
void user_nor_flash_spi_init(void) {
    if(is_nor_flash_init_flag){
        return;
    }

    //不需要重映射
#if SPI0_IO_REMAP
    GPIOPinRemap(ENABLE, RB_PIN_SPI0);
#endif

    GPIO_ResetBits(SPIM0_SS_PORT, SPIM0_SS_PIN);
    GPIO_ModeCfg(SPIM0_SS_PORT, SPIM0_SS_PIN, GPIO_ModeOut_PP_5mA);
    GPIO_ModeCfg(SPIM0_SCK_PORT, SPIM0_SCK_PIN, GPIO_ModeOut_PP_5mA);
    GPIO_ModeCfg(SPIM0_MOSI_PORT, SPIM0_MOSI_PIN, GPIO_ModeOut_PP_5mA);

    SPI0_MasterDefInit();
    //先设置为15M
    SPI0_CLKCfg(4);
    R8_SPI0_CTRL_CFG |= RB_SPI_MST_DLY_EN;
    SPI0_DataMode(Mode0_HighBitINFront);

    //需要拉高，不然会读写数据失败
    USER_NRF_SPI_NSS_H();

    is_nor_flash_init_flag = true;
}

void user_nor_flash_spi_uninit(void) {
    if(!is_nor_flash_init_flag){
        return;
    }

    //不需要重映射
    //GPIOPinRemap(ENABLE, RB_PIN_SPI0);

 //   GPIO_ResetBits(SPIM0_SS_PORT, SPIM0_SS_PIN);
//    GPIO_ModeCfg(SPIM0_SS_PORT, SPIM0_SS_PIN, GPIO_ModeIN_PU);
//    GPIO_ModeCfg(SPIM0_SCK_PORT, SPIM0_SCK_PIN, GPIO_ModeIN_PU);
//    GPIO_ModeCfg(SPIM0_MOSI_PORT, SPIM0_MOSI_PIN, GPIO_ModeIN_PU);

    GPIO_ModeCfg(SPIM0_MISO_PORT, SPIM0_MISO_PIN, GPIO_ModeIN_PD);
    GPIO_ModeCfg(SPIM0_SCK_PORT, SPIM0_SCK_PIN, GPIO_ModeIN_PD);
    GPIO_ModeCfg(SPIM0_MOSI_PORT, SPIM0_MOSI_PIN, GPIO_ModeIN_PD);

    is_nor_flash_init_flag = false;
}

__attribute__((section(".highcode")))
static uint8_t SPI_FLASH_SentByte(uint8_t data) {
    R8_SPI0_CTRL_MOD &= ~RB_SPI_FIFO_DIR;
    R8_SPI0_BUFFER = data; // 启动传输
    while(!(R8_SPI0_INT_FLAG & RB_SPI_FREE));
    return (R8_SPI0_BUFFER); //接收这里需要确认
}

/*******************************************************************************
*函数名：  SPI_FLASH_ReadID
*功能：    读出UID
*入口参数：
*返回参数：
*作者：    Frank
*******************************************************************************/
uint32_t SPI_FLASH_ReadID(void)
{
    uint32_t Temp=0,Temp0=0,Temp1=0,Temp2=0;
    FLASH_SPI_CS_LOW;

    SPI_FLASH_SentByte(W25X_JedecDeviceID);

    Temp0 = SPI_FLASH_SentByte(Dummy_Byte);
    Temp1 = SPI_FLASH_SentByte(Dummy_Byte);
    Temp2 = SPI_FLASH_SentByte(Dummy_Byte);

    FLASH_SPI_CS_HIGH;

    Temp = (Temp0<<16) | (Temp1<<8) | Temp2;

    return Temp;
}

void SPI_FLASH_WriteEnable(void)
{
    FLASH_SPI_CS_LOW;
    SPI_FLASH_SentByte(W25X_WriteEnable);
    FLASH_SPI_CS_HIGH;
}

void SPI_FLASH_WaiteForWriteEnd(void)
{
    uint8_t FLAG = 0;

    FLASH_SPI_CS_LOW;

    SPI_FLASH_SentByte(W25X_ReadStatusReg);
    do
    {
        FLAG = SPI_FLASH_SentByte(Dummy_Byte);
    }
    while((FLAG & WIP_Flag ) == 1);

    FLASH_SPI_CS_HIGH;
}


void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
    SPI_FLASH_WriteEnable();
    SPI_FLASH_WaiteForWriteEnd();

    FLASH_SPI_CS_LOW;

    SPI_FLASH_SentByte(W25X_SectorErase);

    SPI_FLASH_SentByte((SectorAddr>>16)&0xff);
    SPI_FLASH_SentByte((SectorAddr>>8)&0xff);
    SPI_FLASH_SentByte(SectorAddr&0xff);

    FLASH_SPI_CS_HIGH;
    SPI_FLASH_WaiteForWriteEnd();
}

/**
  * @brief  Erases the entire QSPI memory.This function will take a very long time.
  * @retval QSPI memory status
  */
void SPI_FLASH_EraseChip(void)
{
    /* Enable write operations */
    SPI_FLASH_WriteEnable();
    SPI_FLASH_WaiteForWriteEnd();

    /*Select the FLASH: Chip Select low */
    FLASH_SPI_CS_LOW;
    /* Send the read ID command */
    SPI_FLASH_SentByte(W25X_ChipErase);
    /*Deselect the FLASH: Chip Select high */
    FLASH_SPI_CS_HIGH;
    SPI_FLASH_WaiteForWriteEnd();
}

void SPI_FLASH_PageWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumberByteToWrite)
{
    SPI_FLASH_WriteEnable();
    //SPI_FLASH_WaiteForWriteEnd();

    FLASH_SPI_CS_LOW;
    SPI_FLASH_SentByte(W25X_PageProgram);

    SPI_FLASH_SentByte((WriteAddr>>16)&0xff);
    SPI_FLASH_SentByte((WriteAddr>>8)&0xff);
    SPI_FLASH_SentByte(WriteAddr&0xff);

    if(NumberByteToWrite > 256)
    {
        NumberByteToWrite = 256;
        DEBUG_Printf("chang to 256");
    }

    while(NumberByteToWrite--)
    {
        SPI_FLASH_SentByte(*pBuffer);
        pBuffer++;
    }
    FLASH_SPI_CS_HIGH;
    SPI_FLASH_WaiteForWriteEnd();
}

void  SPI_FLASH_SectorWrite(uint8_t *pBuffer,uint32_t WriteAddr,uint16_t NumberByteToWrite){
    uint16_t i = 0;
    uint16_t write_count = NumberByteToWrite / 256;

    for(i = 0; i < write_count; i++){
        SPI_FLASH_PageWrite(pBuffer+i*256, i*256, 256);
    }
    SPI_FLASH_PageWrite(pBuffer+i*256, i*256, NumberByteToWrite %256);
}

void SPI_FLASH_BufferRead(uint8_t *pBuffer,uint32_t ReadAddr,uint16_t NumberByteToRead)
{
    user_nor_flash_spi_init();

    FLASH_SPI_CS_LOW;
    SPI_FLASH_SentByte(W25X_ReadData);

    SPI_FLASH_SentByte((ReadAddr>>16)&0xff);
    SPI_FLASH_SentByte((ReadAddr>>8)&0xff);
    SPI_FLASH_SentByte(ReadAddr&0xff);

    while(NumberByteToRead--)
    {
        *pBuffer = SPI_FLASH_SentByte(Dummy_Byte);
        pBuffer++;
    }
    FLASH_SPI_CS_HIGH;
}

static write_extern_voice_demo(void){
    //SPI_FLASH_SectorErase(0x00000);
//    SPI_FLASH_EraseChip();
//
//    extern unsigned char  external_voice_pcm_add_admin[ EXTERNAL_VOICE_PCM_ADD_ADMIN_LEN +EXTERNAL_VOICE_PCM_ADD_KEY_LEN];
//    SPI_FLASH_SectorWrite(external_voice_pcm_add_admin, 0X00000,EXTERNAL_VOICE_PCM_ADD_ADMIN_LEN+EXTERNAL_VOICE_PCM_ADD_KEY_LEN);

//    extern unsigned char  external_voice_pcm_add_key[ EXTERNAL_VOICE_PCM_ADD_KEY_LEN ];
//    SPI_FLASH_SectorWrite(external_voice_pcm_add_key, EXTERNAL_VOICE_PCM_ADD_ADMIN_LEN, EXTERNAL_VOICE_PCM_ADD_KEY_LEN);
}
//uint8_t Rx_Buffer[1024+256] = {0};
uint8_t SPI_FLASH_init(void){

    user_nor_flash_spi_init();

    uint32_t DeviceID;
    uint8_t  Manufactuer_ID,Memory_Tyep,Capacity;
    DeviceID       = SPI_FLASH_ReadID();
    Manufactuer_ID = (DeviceID >> 16)&0XFF;
    Memory_Tyep    = (DeviceID >> 8)&0XFF;
    Capacity       = DeviceID & 0xff;
    DEBUG_Printf("Manufactuer_ID: 0x%x \n Memory_Tyep: 0x%x \n Capacity: 0x%x\n"
            ,Manufactuer_ID,Memory_Tyep,Capacity);

    if(Capacity == 0x12){
        return 1;
    }
    DEBUG_Printf("SPI_FLASH_init fail\r\n");
  // write_extern_voice_demo();

    //SPI_FLASH_BufferRead(Rx_Buffer,0x00000+2048,1024+256);
    //dk_log_hex("Rx_Buffer", Rx_Buffer, 256);
   // wz_audio_play(Rx_Buffer, 1024+256);
    return 0;
}

#endif
